package cz.muni.fi.pa165.languageschool.rest.client.app;

import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
 * Class for manipulation with Course entity
 *
 * @author Marketa Trachtova (255498) marketa.tr(at)gmail.com
 */
class Course {

    //parameters of the course
    Courses courses;
    String name;
    String code;
    String requiredLevel;
    String taughtLanguage;
    String targetBase;

    /**
     * Constructor of course which is using for initialization of course
     *
     * @param courses set of courses to which will belong that course
     */
    public Course(Courses courses, String base) {
        this.courses = courses;
        this.targetBase = base;

    }

    /**
     * This method is used for creating new course on the server. If some
     * problem occur it will inform user about that
     */
    public void newCourse() {
        Response response;
        try {
            Client client = ClientBuilder.newClient();
            WebTarget webTarget = client.target(targetBase).path("courses/");

            name = Helper.setParam("name");
            code = Helper.setParam("code");
            requiredLevel = Helper.setParam("requiredLevel");
            taughtLanguage = setLanguage();

            String input = "{\"type\":\"courseResource\","
                    + code + ",\"id\":2,"
                    + name + ",\"relatedLectures\":[],"
                    + requiredLevel + ","
                    + taughtLanguage + "}";

            response = webTarget.request()
                    .post(Entity.entity(input, MediaType.APPLICATION_JSON));

            if (response.getStatus() != 201) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + response.getStatus());
            } else {
                System.out.println("++++++ Course was succesfully created ++++++");
            }
        } catch (Exception ex) {
            System.out.println("We are sorry, something went wrong and now have: " + ex.getMessage());
        }

    }

    /**
     * Method which is used for setting language of the course
     *
     * @return resp String which contains name of the course
     */
    private String setLanguage() {
        Object param;

        printLanguage();
        param = Helper.getResponse("Set language:", "c", "e", "g", "f", "s", "m", "h", "a", "p", "r", "sw", "se", "i", "d");

        String language = languageSetter(param);
        String resp = "\"taughtLanguage\":\"" + language.toUpperCase() + "\"";
        return resp;

    }

    /**
     * Method which returns language of the course
     *
     * @return resp String with name of the course
     */
    private String getLanguage() {
        Object param;

        printLanguage();
        param = Helper.getResponse("Set language:", "c", "e", "g", "f", "s", "m", "h", "a", "p", "r", "sw", "se", "i", "d");

        String language = languageSetter(param);
        String resp = "\"" + language.toUpperCase() + "\"";
        return resp;

    }

    /**
     * updateCourse is used for course updating. User can choose which parameter
     * of the course wants to change. In order to update course user needs to
     * insert id of the course which wants to update. After application will ask
     * him to choose which parameter wants to update. Possibilities: "b" (back),
     * "c" (code), "n" (name), "l" (required level), "la" (taught language),
     * "le" (lectures) In case that some error occur application will inform
     * user about that
     */
    public void updateCourse() {

        try {

            Object resp = Helper.getResponse("Set id of course you want to update:", Integer.class);
            if (resp == null) {
                return;
            }
            Integer id = (Integer) resp;

            String course = printCourse(id);
            Map<String, String> map = new HashMap(Helper.toMap(course));
            String out = "";

            printUpdate();
            Object resp1 = Helper.getResponse("Choose which feature you would like to update:", "b", "c", "n", "l", "la", "le");
            switch ((String) resp1) {
                case "b":
                    return;
                case "c":
                    out = Helper.getParam("code");
                    map.put("\"code\"", out);
                    break;
                case "n":
                    out = Helper.getParam("name");
                    map.put("\"name\"", out);
                    break;
                case "l":
                    out = Helper.getParam("requiredLevel");
                    map.put("\"requiredLevel\"", out);
                    break;
                case "la":
                    out = getLanguage();
                    map.put("\"taughtLanguage\"", out);
                    break;
                case "le":
                    //   System.out.println("We are sorry but this si a trial version. To manage lectures please purchase full version of our product.");
                    return;
                default:
                    ;
                    break;

            }

            Client client = ClientBuilder.newClient();
            WebTarget webTarget = client.target(targetBase).path("courses/");

            String input = map.toString();
            input = input.replaceAll("=", ":");

            Response response = webTarget.request()
                    .put(Entity.entity(input, MediaType.APPLICATION_JSON));

            if (response.getStatus() != 201) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + response.getStatus());
            }

            System.out.println("++++++ Course succesfully updated: ++++++");
            printCourse(id);

        } catch (Exception ex) {
            System.out.println("We are sorry, something went wrong and now we have : " + ex.getMessage());
        }

    }

    /**
     * This method is used for deleting course When this method is called user
     * needs to add id of the course which wants to delete Method will inform
     * user if course is successfully deleted or if some problem occur
     */
    public void deleteCourse() {

        try {
            printCancle();
            Object resp = Helper.getResponse("Set id of course you want to delete:", "c", Integer.class);
            if (resp == null) {
                return;
            } else {
                if ("c".equals(resp)) {
                    return;
                }
            }

            Integer id = (Integer) resp;
            Client client = ClientBuilder.newClient();
            WebTarget webTarget = client.target(targetBase)
                    .path("courses/" + id.toString());

            Invocation.Builder invocationBuilder
                    = webTarget.request(MediaType.APPLICATION_JSON)
                    .header("accept", "application/json");

            Response response = invocationBuilder.delete();

            if (response.getStatus() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + response.getStatus());
            }

            String done = response.readEntity(String.class);
            System.out.println("+++++ Course succesfully deleted +++++");

        } catch (Exception ex) {
            System.out.println("We are sorry, something went wrong and now we have : " + ex.getMessage());
        }

    }

    /**
     * Method printCourses() is used for printing all courses from the database
     * on the standard output.
     */
    public void printCourses() {
        System.out.println("+++++++ All courses +++++++");
        try {
            Client client = ClientBuilder.newClient();
            WebTarget webTarget = client.target(targetBase).path("courses/json/");

            Invocation.Builder invocationBuilder
                    = webTarget.request(MediaType.APPLICATION_JSON)
                    .header("accept", "application/json");

            Response response = invocationBuilder.get();

            if (response.getStatus() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + response.getStatus());
            }

            String resp = response.readEntity(String.class);
            String newResp;

            newResp = resp.replaceAll("\\[|\\]", "");
            resp = newResp.replaceAll("\"type\":\"courseResource\"", "");
            for (String s : resp.split("\\{|\\}")) {
                for (String st : s.split("\\,")) {
                    st.replace("\\}", "");
                    System.out.println(st);
                }
                System.out.println("----");
            }
            System.out.println("+++++++++++++++++++++++++++++++++");
        } catch (Exception ex) {
            System.out.println("We are sorry, something went wrong and now we have: " + ex.getMessage());
        }
    }

    /**
     * This method returns course with given Id
     *
     * @param id id of the course which will be returned
     * @return raw - parameter contains string about course
     */
    public String printCourse(Integer id) {
        String raw;
        System.out.println("+++++++ Requested course: +++++++");
        try {
            Client client = ClientBuilder.newClient();
            WebTarget webTarget = client.target(targetBase)
                    .path("courses/json/" + id.toString());

            Invocation.Builder invocationBuilder
                    = webTarget.request(MediaType.APPLICATION_JSON)
                    .header("accept", "application/json");

            Response response = invocationBuilder.get();

            if (response.getStatus() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + response.getStatus());
            }
            raw = Helper.prinStringResponse(response);
            System.out.println("+++++++++++++++++++++++++++++++++");

            return raw;
        } catch (Exception ex) {
            System.out.println("We are sorry, something went wrong and now we have: " + ex.getMessage());
        }
        return null;
    }

    /**
     * This method is used for choosing language of the course
     *
     * @param param - String which represent language
     * @return language - String with full name of the language
     */
    private String languageSetter(Object param) {

        String language;
        switch ((String) param) {
            case "c":
                language = "Czech";
                break;
            case "e":
                language = "English";
                break;
            case "g":
                language = "German";
                break;
            case "s":
                language = "Spanish";
                break;
            case "f":
                language = "French";
                break;
            case "m":
                language = "Mandarin";
                break;
            case "h":
                language = "Hindi";
                break;
            case "a":
                language = "Arabic";
                break;
            case "p":
                language = "Portuguese";
                break;
            case "r":
                language = "Russian";
                break;
            case "sw":
                language = "Swahili";
                break;
            case "se":
                language = "Serbian";
                break;
            case "i":
                language = "Italian";
                break;
            case "d":
                language = "Dutch";
                break;
            default:
                language = "Czech";
                break;

        }
        return language;
    }

    /**
     * Auxiliary method which lists all options for course updating on standard
     * output b - Back n - new Name c - new Code l - new Level la - new Language
     * le - manage Lectures
     */
    private void printUpdate() {
        System.out.println("_____");
        System.out.println("b - Back");
        System.out.println("n - new Name");
        System.out.println("c - new Code");
        System.out.println("l - new Level");
        System.out.println("la - new Language");
    }

    /**
     * Auxiliary method printCancle() prints message for action cancel on the
     * standard output
     */
    private void printCancle() {
        System.out.println("_____");
        System.out.println("c - Cancle or");

    }

    /**
     * Auxiliary method printLanguage() prints codes for languages which can be
     * set for the curse
     */
    private void printLanguage() {
        System.out.println("_____");
        System.out.println("Choose language from:");
        System.out.println("c - Czech");
        System.out.println("e - English");
        System.out.println("g - German");
        System.out.println("s - Spanish");
        System.out.println("f - French");
        System.out.println("m - Mandarin");
        System.out.println("h - Hindi");
        System.out.println("a - Arabic");
        System.out.println("p - Portuguese");
        System.out.println("r - Russian");
        System.out.println("sw - Swahili");
        System.out.println("se - Serbian");
        System.out.println("i - Italian");
        System.out.println("d - Dutch");

    }
}
